#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''=================================================
@Project -> File   ：
@IDE    ：PyCharm
@Author ：Json
@Date   ：2021-03-08 10:45
@Desc   ：获取CS用户信息
=================================================='''
import base64
import time
import logging
from retrying import retry
from cs_token.authorization_get import CsAuthorization
from cs_token.sql.cs_user_info_sql import CsUserInfoSql
logger = logging.getLogger(__name__)

class CSUserVir:
    def __init__(self, rcustomerno):
        """
        :param Rcustomerno: can cs_user_name str cs_user_num
        """
        self.rcustomerno = rcustomerno
        self.vir = True
        self.cs_user_num = rcustomerno
        self.hk_account = True
        self.us_account = True


class CSUser:
    def __init__(self, rcustomerno, mysql_db):
        """
        :param Rcustomerno: can cs_user_name str cs_user_num
        """
        self.rcustomerno = rcustomerno
        self.cs_info_sql = CsUserInfoSql(mysql_db)
        self.cs_user_info = self.get_cs_user_info()
        self.cs_user_name = self.cs_user_info.get('cs_name')
        self.cs_password = self.cs_user_info.get('cs_password')
        self.cs_user_num = self.cs_user_info.get('Rcustomerno')
        self.token = self.cs_user_info.get('token')
        self.exp_time = self.cs_user_info.get('exp_time')
        self.exp_times_tamp = self.cs_user_info.get('exp_times_tamp')
        self.init_token()  # 初始化token，从数据库读取，如果过期则重新获取
        self.hk_account = True
        self.us_account = True

    def get_cs_user_info(self):
        cs_info = self.cs_info_sql.get_cs_user_info(self.rcustomerno)
        return cs_info

    def add_token_to_sql(self, exp_times_tamp, token_time, token_str, customer_id):
        self.cs_info_sql.add_token(exp_times_tamp, token_time, token_str, customer_id)

    def init_token(self):
        """
        从文本获取token，不够通用。改为从数据库获取
        :return:
        """
        if self.cs_user_info:
            if all([self.exp_times_tamp, self.exp_time, self.token]):  # 检查从数据库获取的token信息，都为不为空，检查是否过期，否则重新获取
                self.is_expired()  # 检查token是否过期
            else:
                self.get_token_complete()
        else:
            logger.info('bm 用户没有匹配的cs账户。无法处理订单')

    def is_expired(self):
        # 每次使用token 需检查一下是否过期,比较时间戳
        time_difference = int(self.exp_times_tamp) - int(time.time())
        if int(self.exp_times_tamp) > int(time.time()) + 1000:  # 为了保险，将过期时间提前1000秒
            logger.info('用户{0}token在{1}s 后过期'.format(self.cs_user_num, time_difference))
            return True  # 未过期
        else:
            logger.info('重新获取token')
            try:
                self.get_token_complete()
            except Exception as e:
                logger.info(f'获取token失败:{str(e)}')
                return False
            return False

    def get_token_complete(self):
        """
        从cs请求最新的token
        :return:
        """

        cs_token = self.get_cs_token()

        if cs_token:
            self.exp_times_tamp, self.exp_time, self.token = self.parser_token(cs_token)  # 每次获取token，重新获取过期时间
            self.add_token_to_sql(self.exp_times_tamp, self.exp_time, self.token,
                                  self.cs_user_num)  # 将最新的token信息存到数据库
        else:
            cs_token = self.get_cs_token()
            logger.info('code码错误，重试')
            if cs_token:
                self.exp_times_tamp, self.exp_time, self.token = self.parser_token(cs_token)  # 每次获取token，重新获取过期时间
                self.add_token_to_sql(self.exp_times_tamp, self.exp_time, self.token,
                                      self.cs_user_num)  # 将最新的token信息存到数据库
            else:
                raise Exception('获取token失败')

    @retry(stop_max_attempt_number=3, wait_fixed=10 * 1000)
    def get_cs_token(self):
        Token_obj = CsAuthorization(self, input_code=False)
        cs_token = Token_obj.get_access_token()  # json 形式
        if cs_token:
            return cs_token
        else:
            raise Exception('获取token 异常')

    def parser_token(self, cs_token):
        """
        解析token，获取真实的过期时间，获取token的过期时间
        :return: 时间戳
        """
        token = cs_token[u'result'][u'token']
        token_str = token.split('.')[1]
        missing_padding = 4 - len(token_str) % 4
        if missing_padding:
            token_str += '=' * missing_padding
        base64_str = base64.b64decode(token_str)
        token_info = eval(base64_str)
        token_timestruct = token_info['exp']
        customerNo = token_info['customerNo']
        if customerNo == self.cs_user_num:
            time_obj = time.localtime(token_timestruct)  # 转成time.struct_time 对象，程序使用的对象，
            token_time = time.strftime("%Y-%m-%d %H:%M:%S", time_obj)
            logger.info('token过期时间{0}'.format(token_time))
            logger.info("信息一致")
            return token_timestruct, token_time, token  # 时间戳，明文时间，token base64加密字符串
        else:
            logger.error('用户信息错误')
            logger.error(base64_str)
            raise Exception('用户信息错误')


if __name__ == '__main__':
    cs_user = CSUser('2258')
    print(cs_user.cs_user_name)
    print(cs_user.cs_password)
    print(cs_user.cs_user_num)
    print(cs_user.token)
    print(cs_user.exp_time)
    print(cs_user.exp_times_tamp)
